/*
 *  PPXMLEntity.m
 *  PigeonsFoundation
 *
 *  Created by Jacob Basham on 2/2/07.
 *  Copyright 2007, PaperPigeons.net
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without 
 *  modification, are permitted provided that the following conditions 
 *  are met:
 *  1. Redistributions of source code must retain the above copyright 
 *     notice, this list of conditions and the following disclaimer.
 *	2. Redistributions in binary form must reproduce the above copyright 
 *	   notice, this list of conditions and the following disclaimer in 
 *	   the documentation and/or other materials provided with the distribution.
 *	3. Neither the name of PaperPigeons.net nor the names of its contributors 
 *	   may be used to endorse or promote products derived from this software 
 *	   without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 *	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 *	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 *	FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 *	COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 *	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 *	BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 *	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 *	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 *	LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
 *	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 *	POSSIBILITY OF SUCH DAMAGE.
 */

#import "PPXMLEntity.h"


@implementation PPXMLEntity

+ (id)XMLEntityWithDescription:(PPXMLEntityDescription *)description 
		parent:(PPXMLEntity *)parent
{
	id this = [[super alloc] initWithDescription:description];
	[this setParent:parent];
	return this;
}

- (id)initWithDescription:(PPXMLEntityDescription *)description
{
	if (self = [super init]) {
		_description = [description retain];
	}
	return self;
}

- (PPXMLEntityDescription *)entityDescription
{
	return _description;
}

- (NSXMLElement *)element
{
	id temp;
	NSArray * items;
	NSString * each;
	NSXMLNode * node;
	NSEnumerator * enumerator;
	NSXMLElement * element = [NSXMLElement elementWithName:[_description name]];
	
	// attach any attributes
	items = [_description valueForKey:@"attributes"];
	enumerator = [items objectEnumerator];
	while (each = [enumerator nextObject]) {
		temp = [self valueForKey:each];
		if (temp) {
			node = [NSXMLNode attributeWithName:each stringValue:temp];
			[element addAttribute:node];
		}
	}
	
	// attach any character nodes
	items = [_description valueForKey:@"characterNodes"];
	enumerator = [items objectEnumerator];
	while (each = [enumerator nextObject]) {
		temp = [self valueForKey:each];
		if (temp) {
			node = [NSXMLNode elementWithName:each stringValue:temp];
			[element addChild:node];
		}
	}
	
	// attach any children nodes
	items = [_description valueForKey:@"children"];
	enumerator = [items objectEnumerator];
	while (each = [enumerator nextObject]) {
		temp = [self valueForKey:each];
		if (temp) {
			[temp addChild:[temp element]];
		}
	}
	
	return element;
}

- (void)actionFromReader:(PPXMLReader *)reader
{
	id temp;
	
	// if end of this element return to parent
	if ([reader isEndElementEqualToString:[_description name]]) {
		[reader setDelegate:_parent];
		return;
	}
	
	// if begining of child element initialize and delegate control
	int child = [[_description valueForKey:@"children"] indexOfObject:[reader name]];
	if (child != NSNotFound) {
		temp = [PPXMLEntity XMLEntityWithDescription:[[_description valueForKey:@"children"] objectAtIndex:child] parent:self];
		[self setValue:temp forKey:[reader name]];
		
		// if node has attributes
		if ([reader hasAttributes]) {
			NSString * attribute;
			NSArray * attributes = [[temp entityDescription] attributes];
			NSEnumerator * enumerator = [attributes objectEnumerator];
			
			// get each attribute and store in object
			while (attribute = [enumerator nextObject]) {
				NSString * tempAttr = [reader getAttribute:attribute];
				if (tempAttr) {
					[temp setValue:tempAttr forKey:attribute];
				}
			}
		}
		
		// if child element isn't empty, set delegate to child object
		if (![reader isEmptyElement]) {
			[reader setDelegate:temp];
		}
		
		return;
	}
	
	// if begining of character node retain name
	int text = [[_description valueForKey:@"characterNodes"] indexOfObject:[reader name]];
	if (text != NSNotFound) {
		_textName = [[reader name] retain];
		return;
	}
	
	// if node is character data and name is retained set value
	if ([reader isCharacterData] && _textName) {
		[self setValue:[reader characters] forKey:_textName];
		[_textName release];
		return;
	}
}

- (void)dealloc
{
	[_description release];
	[super dealloc];
}

@end
